{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 字典集锦"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 字典的默认值\n",
    "- ``collections.defaultdict``可以对字典定义初始值，免去“先判断键存在与否再设定初始值”的操作；\n",
    "- dictObject.setdefault(key, default)也能做到默认初始，但明显collections.defaultdict更简洁"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "defaultdict(<class 'list'>, {'a': [1], 'b': [2], 'c': [3]})\n",
      "{'a': [1], 'b': [2], 'c': [3]}\n"
     ]
    }
   ],
   "source": [
    "from collections import defaultdict\n",
    "\n",
    "d1 = defaultdict(list)\n",
    "d1['a'].append(1)\n",
    "d1['b'].append(2)\n",
    "d1['c'].append(3)\n",
    "\n",
    "# 使用setdefault\n",
    "d2 = dict()\n",
    "d2.setdefault('a', []).append(1)\n",
    "d2.setdefault('b', []).append(2)\n",
    "d2.setdefault('c', []).append(3)\n",
    "\n",
    "print(d1)\n",
    "print(d2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 让字典保持有序\n",
    "- ``collections.OrderedDict`` 最字典做迭代时，OrderDict会严格根据元素初始添加顺序进行\n",
    "- OrderDict的大小会是普通字典的2倍，因为它需要一个同样大小的链表来记录元素添加顺序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "foo 1\n",
      "bar 2\n",
      "spam 3\n"
     ]
    }
   ],
   "source": [
    "from collections import OrderedDict\n",
    "\n",
    "d = OrderedDict()\n",
    "d['foo'] = 1\n",
    "d['bar'] = 2\n",
    "d['spam'] = 3\n",
    "\n",
    "for key in d.keys():\n",
    "    print(key, d[key])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 键与值相关的运算\n",
    "- 使用``zip``可以灵活选择对键或值进行运算\n",
    "- ``zip``创建了一个迭代器，它的内容只能被消费一次"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10.75, 'FB') (612.78, 'AAPL')\n"
     ]
    }
   ],
   "source": [
    "prices = {\n",
    "    \"ACME\": 45.23,\n",
    "    \"AAPL\": 612.78,\n",
    "    \"IBM\": 205.55,\n",
    "    \"HPQ\": 37.20,\n",
    "    \"FB\": 10.75,\n",
    "}\n",
    "\n",
    "#  求价格最低和最高的股票\n",
    "min_price = min(zip(prices.values(), prices.keys()))\n",
    "max_price = max(zip(prices.values(), prices.keys()))\n",
    "print(min_price, max_price)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 字典中的交并集\n",
    "- 字典对象中，``keys()``返回的键，以及``items()``返回的对象是可以进行交集并集运算的；\n",
    "- ``values()``返回的值无法进行集合运算，因为不能保证值都是唯一；"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'x', 'y'}\n",
      "{'z'}\n",
      "{('x', 1), ('y', 2)}\n",
      "{('z', 3)}\n",
      "{'c': 3}\n"
     ]
    }
   ],
   "source": [
    "a = {'x':1, 'y':2, 'z':3}\n",
    "b = {'x':1, 'y':2, 'c':3}\n",
    "print(a.keys() & b.keys())\n",
    "print(a.keys()-b.keys())\n",
    "print(a.items() & b.items())\n",
    "print(a.items()-b.items())\n",
    "\n",
    "# 删除字典中的某些键\n",
    "c = {key:b[key] for key in b.keys() - {'x', 'y'}}\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.7.4 64-bit",
   "language": "python",
   "name": "python37464bit0eab7a6caf29454899b876d50238c56e"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
